/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package javaapplication1;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author new
 */
public class LabelHandler {


    public LabelHandler() throws FileNotFoundException, IOException{
        getReverseTable();
    }

    public int getLabelTable(String FileName) throws FileNotFoundException, IOException{

        Pattern pattern;
        Matcher matcher;
        labelTable = new ArrayList();
        pattern = Pattern.compile("\\w*(?=\\s{0,65536}:)",Pattern.CASE_INSENSITIVE);
        FileHandler fh = new FileHandler();
        BufferedReader br = fh.openReadFile(FileName);
        String tempStr = br.readLine();
        while(tempStr != null){
            matcher =pattern.matcher(tempStr);
            if(matcher.find()){
                if(labelTable.contains(matcher.group())){
                    System.out.println(matcher.group() + "define twice");
                    System.exit(0);
                } else {
                    if(isConflictWithReverse(matcher.group())){
                        System.out.println(matcher.group() + " is conflict with reverse word.");
                        System.exit(0);
                    } else {
                        if(isConflictWithSegment(matcher.group())){
                            System.out.println(matcher.group() + " is conflict with segment label.");
                            System.exit(0);
                        } else {
                            labelTable.add(matcher.group());
                        }
                    }
                }
            }
            tempStr = br.readLine();
        }

        fh.closeReadFile(br);

        labelTableLength = labelTable.size();

        return labelTableLength;
    }

    public int getSegmentTable(String FileName) throws FileNotFoundException, IOException{
        Pattern pattern;
        Matcher matcher;
        segTable = new ArrayList();
        segInfoTable = new ArrayList();
        ArrayList rsegTable;
        pattern = Pattern.compile("\\w*(?=\\s{0,65536}\\bSEGMENT\\b)",Pattern.CASE_INSENSITIVE);
        FileHandler fh = new FileHandler();
        BufferedReader br = fh.openReadFile(FileName);
        String tempStr = br.readLine();
        while(tempStr != null){
            if(tempStr.contains("SEGMENT")){
                matcher =pattern.matcher(tempStr);
                if(matcher.find()){
                    if(segTable.contains(matcher.group())){
                        System.out.println(matcher.group() + "define twice");
                        System.exit(0);
                    } else {
                        if(isConflictWithReverse(matcher.group())){
                            System.out.println(matcher.group() + " is conflict with reverse word or has special characters.");
                            System.exit(0);
                        } else {
                            segTable.add(matcher.group());
                            segInfoTable.add(tempStr);
                        }
                    }
                } else {
                    System.out.println("SEGMENT should have a label");
                    System.exit(0);
                }
            }
            tempStr = br.readLine();
        }
        rsegTable = new ArrayList(segTable);
        fh.closeReadFile(br);

        pattern = Pattern.compile("(?<=\\bRSEG\\b\\s{0,65536})\\w*",Pattern.CASE_INSENSITIVE);
        br = fh.openReadFile(FileName);
        tempStr = br.readLine();
        while(tempStr != null){
            if(tempStr.contains("RSEG")){
                matcher =pattern.matcher(tempStr);
                if(matcher.find()){
                    if(rsegTable.contains(matcher.group())){
                        rsegTable.remove(matcher.group());
                    } else {
                        if(segTable.contains(matcher.group())){
                            System.out.println(matcher.group() + " has two RSEG");
                            System.exit(0);
                        } else {
                            System.out.println(matcher.group() + " do not have a SEGMENT.");
                            System.exit(0);
                        }
                    }
                } else {
                    System.out.println("RSEG should have a label.");
                    System.exit(0);
                }
            }
            tempStr = br.readLine();
        }
        int length = rsegTable.size();

        for(int i = 0; i < length; i++){
            System.out.println(rsegTable.get(i) + "do not have RSEG.");
        }
        if(length != 0){
            System.exit(0);
        }
        segTableLength = segTable.size();

        return segTableLength;
    }

    public int delSegment(String FileName) throws FileNotFoundException, IOException{
        Pattern pattern;
        Matcher matcher;
        pattern = Pattern.compile("\\w*(?=\\s{0,65536}\\bSEGMENT\\b)",Pattern.CASE_INSENSITIVE);
        FileHandler fh = new FileHandler();
        BufferedReader br = fh.openReadFile(FileName);
        String temp = "SegmentTemp";
        BufferedWriter bw = fh.openWriteFile(temp);
        String tempStr = br.readLine();
        while(tempStr != null){
            matcher =pattern.matcher(tempStr);
            if(matcher.find()){
                tempStr = br.readLine();
                continue;
            }
            bw.append(tempStr);
            bw.newLine();
            tempStr = br.readLine();
        }
        fh.closeReadFile(br);
        fh.closeWriteFile(bw);
        System.gc();
        fh.replaceFile(temp, FileName);

        return 0;
    }

    private void getReverseTable() throws FileNotFoundException, IOException {
        reverseTable = new ArrayList();
        reverseTable.add("MOV");
        reverseTable.add("NOP");
        reverseTable.add("XCSD");
        reverseTable.add("SFA");
        reverseTable.add("LAF");
        reverseTable.add("ANL");
        reverseTable.add("ORL");
        reverseTable.add("XRL");
        reverseTable.add("RL");
        reverseTable.add("RLC");
        reverseTable.add("RR");
        reverseTable.add("RRC");
        reverseTable.add("INC");
        reverseTable.add("DEC");
        reverseTable.add("SET");
        reverseTable.add("CLR");
        reverseTable.add("CPL");
        reverseTable.add("ADD");
        reverseTable.add("ADDC");
        reverseTable.add("SUB");
        reverseTable.add("SUBB");
        reverseTable.add("PJUMP");
        reverseTable.add("PCALL");
        reverseTable.add("LJMP");
        reverseTable.add("LCALL");
        reverseTable.add("DJNZ");
        reverseTable.add("CJNE");
        reverseTable.add("RET");
        reverseTable.add("RETI");
        reverseTable.add("SJMP");
        reverseTable.add("JMP");
        reverseTable.add("JZ");
        reverseTable.add("JNZ");
        reverseTable.add("JC");
        reverseTable.add("JNC");
        reverseTable.add("JPO");
        reverseTable.add("JPE");
        reverseTable.add("JS");
        reverseTable.add("JNS");
        reverseTable.add("PUSH");
        reverseTable.add("POP");
        reverseTable.add("IN");
        reverseTable.add("OUT");
        reverseTable.add("HLT");
        reverseTable.add("INCLUDE");
        reverseTable.add("DEFINE");
        reverseTable.add("ORG");
        reverseTable.add("EQU");
        reverseTable.add("DB");
        reverseTable.add("DS");
        reverseTable.add("CSEG");
        reverseTable.add("RSEG");
        reverseTable.add("SEGMENT");
        reverseTable.add("PUBLIC");
        reverseTable.add("EXTERN");
        reverseTable.add("A");
        reverseTable.add("FLAGS");
        reverseTable.add("R0");
        reverseTable.add("R1");
        reverseTable.add("R2");
        reverseTable.add("R3");
        reverseTable.add("DPH");
        reverseTable.add("DPL");
        reverseTable.add("SPH");
        reverseTable.add("SPL");
        reverseTable.add("DPTR");
        reverseTable.add("SP");
        reverseTable.add("PC");
        reverseTable.add("C");
        reverseTable.add("IE");
        reverseTable.add("RB");
        reverseTable.add("PAGE");
        reverseTable.add("INPAGE");
        reverseTable.add("INBLOCK");
        reverseTable.add("SHARE");
        reverseTable.add("H");
        reverseTable.add("B");
        reverseTable.add("END");
    }

    public static boolean isConflictWithReverse(String in){
        if(reverseTable.contains(in)){
            return true;
        }
        if(NumberHandler.isHex(in) || NumberHandler.isBinary(in) || NumberHandler.isDecimal(in)){
            return true;
        }
        if(hasSpecial(in)){
            return true;
        }
        return false;
        
        
    }

    public static boolean isConflictWithSegment(String in){
        if(segTable.contains(in)){
            return true;
        } else {
            return false;
        }
    }
    
    public static boolean isConfilictWithLabel(String in){
        if(labelTable.contains(in)){
            return true;
        } else {
            return false;
        }
    }

    public int rsegToEnd(String FileName) throws FileNotFoundException, IOException {
        String rsegTemp = "RSEGPartTemp";
        String otherTemp = "OtherPartTemp";
        FileHandler fh = new FileHandler();
        BufferedReader br = fh.openReadFile(FileName);
        BufferedWriter bwRseg = fh.openWriteFile(rsegTemp);
        BufferedWriter bwOther = fh.openWriteFile(otherTemp);
        String tempStr = br.readLine();
        while(tempStr != null){
            boolean hasEnd = false;
            if(tempStr.contains("RSEG")){
                while(true){
                    if(tempStr == null){
                        System.out.println("RSEG block do not have END.");
                        System.exit(0);
                    }
                    if(tempStr.contains("CSEG")){
                        System.out.println("RSEG block cannot have a CSEG inside.");
                        System.exit(0);
                    }
                    if(tempStr.contains("ORG")){
                        System.out.println("RSEG block cannot have a ORG inside.");
                        System.exit(0);
                    }
                    bwRseg.append(tempStr) ;
                    bwRseg.newLine();
                    if(tempStr.contains("END")){
                        hasEnd = true;
                        break;
                    }
                    tempStr = br.readLine();
                }
            }
            if(hasEnd){
                tempStr = br.readLine();
                continue;
            }
            bwOther.append(tempStr);
            bwOther.newLine();
            tempStr = br.readLine();
        }
        fh.closeReadFile(br);
        fh.closeWriteFile(bwRseg);
        fh.closeWriteFile(bwOther);
        System.gc();
        fh.compose(otherTemp, rsegTemp);
        System.gc();
        fh.replaceFile(otherTemp, FileName);
        System.gc();
        File f = new File(rsegTemp);
        f.delete();
        return 0;
    }

    private static boolean hasSpecial(String in) {
        for(int i = 0; i < specialTableLength; i++){
            if(in.contains("" + specialTable.charAt(i))){
                return true;
            }
        }
        return false;
    }



    public static ArrayList labelTable;
    public int labelTableLength;
    public static ArrayList segTable;
    public static ArrayList segInfoTable;
    public int segTableLength;
    private static ArrayList reverseTable;
    private static String specialTable = "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?";
    private static int specialTableLength = specialTable.length();
}
